import { TerrainConfig, TerrainConfigItem, TerrainConfigManager } from "./utils/TerrainConfigManager";
import { WoundedConfigManager } from "./utils/WoundedConfigManager";

interface Cell {
    row: number;
    col: number;
}
/*
 * @Author: zhang
 * @Date: 2025-04-10 10:03:35
 * @Description: 
 * @LastEditors: zhang
 * @LastEditTime: 2025-04-10 11:36:25
 */
export class Wounded extends Laya.Box {
     _terrain: Laya.Image;
    public id: number;
    public icon: string;
    public type: number;
    public img_skin: string;

    public anchorRow: number = 0;
    public anchorCol: number = 0;
    public occupiedGridSprites: any;
    public occupiedGrids: Array<{ row: number, col: number }> = [];

    // Base size in GRID UNITS. Initialize as undefined or null
    // to indicate they haven't been determined yet.
    baseGridWidth: number | undefined = undefined;
    baseGridHeight: number | undefined = undefined;
    public gridSizeCount: number | undefined = undefined;

    // Flag to track if size was explicitly set by config
    private sizeSetFromConfig: boolean = false;

    constructor() {
        super();
        // Basic setup
        this.anchorX = 0.5;
        this.anchorY = 1;
        this.mouseThrough = false;

        this._terrain = new Laya.Image();
        this._terrain.centerX = 0;
        this._terrain.bottom = 0;
        // this.bgColor = "#000000";
        this.addChild(this._terrain);
        // this.getGeneralizedTileCoordinates({ row: 5, col: 1 }, 2, 2)
    }

    /**
     * Initializes the terrain, loading configuration and image.
     * Returns a Promise that resolves when the terrain is fully initialized
     * (including having its base grid size determined, either from config or image).
     *
     * @param config Optional terrain configuration.
     * @param gridLogicWidth The logical width of a grid cell (e.g., 50). Needed for calculation.
     * @param gridRowSpacing The vertical distance between rows (e.g., 25). Needed for calculation.
     * @returns Promise<void>
     */
    public async initWounded(
        config?: TerrainConfigItem,

    ): Promise<void> {
        return new Promise((resolve, reject) => {
            // 1. Apply basic config values
            if (config) {
                this.id = config.id;
                this.type = config.type;
                this.icon = config.icon;
                this.img_skin = config.icon;

                // Check if config provides explicit base size
                if (config.offset) {
                    this._terrain.centerX = config.offset[0];
                    this._terrain.bottom = config.offset[1];
                }

                if (config.size[0] !== undefined && config.size[1] !== undefined) {
                    this.baseGridWidth = config.size[0];
                    this.baseGridHeight = config.size[1];
                    let gridSizeCount = (this.baseGridWidth + this.baseGridHeight) / 2
                    const logicalBaseWidthPx = gridSizeCount * this.gridLogicWidth;
                    const logicalBaseHeightPx = gridSizeCount * this.gridRowSpacing;
                    this.size(logicalBaseWidthPx, logicalBaseHeightPx);
                    this.anchorX = this.baseGridWidth / 2 / gridSizeCount
                    this.gridSizeCount = gridSizeCount
                    this.sizeSetFromConfig = true; // Mark that size came from config
                    console.log(`Terrain ${this.id} initialized. Base size from config: ${this.baseGridWidth}x${this.baseGridHeight} grids.`);
                } else {
                    console.log(`Terrain ${this.id} initialized. Base size will be calculated from image.`);
                }
                // Config position might be less relevant now
            }


            // Clear previous listeners before adding new ones
            this._terrain.offAll();
            // Add LOADED listener


            // Add ERROR listener

            // 4. Initiate loading
            this._terrain.skin = WoundedConfigManager.getInstance().getFullResourcePath(this.img_skin); // Prepend resources path if needed
            // this._terrain.loadImage(WoundedConfigManager.getInstance().getFullResourcePath(this.img_skin), Laya.Handler.create(this, () => {
            //     let scale = this.baseGridWidth * this.gridLogicWidth / this._terrain.displayWidth
            //     this._terrain.height = this._terrain.displayHeight * scale


            // }))
            this._terrain.width = this._terrain.height = this.baseGridWidth * this.gridLogicWidth * 3

        }); // End of Promise constructor
    }
    gridLogicWidth: number = 50 // Provide default grid dimensions
    gridRowSpacing: number = 25

    posGrid = { row: 0, col: 0 }
    /**
     * Calculates the position of the terrain in the grid based on its anchor position.
     *
     * @param anchorPos The anchor position of the terrain.

    /**
  * Calculates occupied grid cells based on the provided reference logic,
  * which seems to create a skewed parallelogram shape.
  * The calculation starts from the anchor cell and uses the baseGridWidth (W)
  * and baseGridHeight (H) as the dimensions for the skewed area.
  *
  * @param gridLogicWidth (Not directly used in this specific logic)
  * @param gridRowSpacing (Not directly used in this specific logic)
  * @param screenX The screen X coordinate of the terrain's anchor (bottom-center).
  * @param screenY The screen Y coordinate of the terrain's anchor (bottom-center).
  * @param localMapGrid The 2D array representing the map state.
  * @param screenToGrid Function to convert screen coords to grid {row, col}.
  * @param gridToScreen Function to convert grid {row, col} to screen {x, y}.
  * @returns boolean - True if all calculated occupied grids are valid, False otherwise.
  */
    public updateOccupiedGrids(
        gridLogicWidth: number,
        gridRowSpacing: number,
        screenX: number,
        screenY: number,
        localMapGrid: Array<Array<{ id: number, x: number, y: number, row: number, column: number, type: number }>>,
        gridData: Array<Array<{ id: number, x: number, y: number, row: number, column: number, type: number }>>,
        screenToGrid: (x: number, y: number) => { row: number, col: number },
        gridToScreen: (row: number, col: number) => { x: number, y: number }
    ): boolean {
        this.occupiedGrids = [];
        let allGridsValid = true;

        // --- Crucial Check: Ensure base size is determined ---
        if (this.baseGridWidth === undefined || this.baseGridHeight === undefined || this.baseGridWidth < 1 || this.baseGridHeight < 1) {
            console.error(`Terrain ${this.id}: Cannot update occupied grids. Base size (W=${this.baseGridWidth}, H=${this.baseGridHeight}) is invalid or not determined.`);
            return false;
        }
        // --- End Check ---

        // 1. Find the grid cell where the bottom-center anchor lands
        // 计算锚点位置时，考虑地形的实际大小和格子的尺寸
        const anchorPos = screenToGrid(
            screenX, // 水平居中 300/2 150
            screenY  // 垂直居中
        )
        this.anchorRow = anchorPos.row; // Starting row 'r'
        this.anchorCol = anchorPos.col; // Starting column 'c'
        console.log(this.anchorRow, this.anchorCol)
        const W = this.baseGridWidth;  // Corresponds to setArea[0] in your reference
        const H = this.baseGridHeight; // Corresponds to setArea[1] in your reference
        this.occupiedGrids = this.generateCells({ row: this.anchorRow, col: this.anchorCol }, { width: W, height: H })
        console.log(this.occupiedGrids)
        for (let i = 0, len = this.occupiedGrids.length; i < len; i++) {
            let cell = this.occupiedGrids[i]
            if (cell.row < 0 || cell.row >= localMapGrid.length ||
                !localMapGrid[cell.row] ||
                cell.col < 0 || cell.col >= localMapGrid[cell.row].length) {
                // Out of bounds
                if (allGridsValid) {
                    allGridsValid = false;
                    return allGridsValid
                }

            } else {
                // Check passability
                const gridType = localMapGrid[cell.row][cell.col];
                if (gridType.type !== 8) { // npc必须在道路上
                    if (allGridsValid) {
                        /* console.warn(...) */
                        allGridsValid = false;
                        return allGridsValid
                    }

                }
                const gridType1 = gridData[cell.row][cell.col];

                if (gridType1.type !== 0) { // npc在没有被占领的格子里面
                    if (allGridsValid) {
                        /* console.warn(...) */
                        allGridsValid = false;
                        return allGridsValid
                    }

                }
            }
        }

        return allGridsValid;
    }


    generateCells(bottomCell: Cell, terrainSize: { width: number; height: number }): Cell[] {
        let { col: x, row: y } = bottomCell;
        const { width, height } = terrainSize;

        let cells: Cell[] = [{ row: y, col: x }]; // 先加入底部格子
        let leftCells: Cell[] = [{ row: y, col: x }]; // 存放往左上的格子
        let rightCells: Cell[] = []; // 存放往右上的格子

        // 计算往左上的 A 个格子
        let cx = x, cy = y;
        for (let i = 0; i < width - 1; i++) { // 左上移动 width-1 步
            if (cy % 2 === 0) { // 偶数行：列和行都减少
                cx -= 1;
            }
            cy -= 1;
            leftCells.push({ row: cy, col: cx });
        }

        console.log(leftCells); // 3x3 地形调试输出

        // 计算 M 中每个格子的右上方向格子
        for (const { row: ly, col: lx } of leftCells) {
            cx = lx;
            cy = ly;
            for (let i = 0; i < height - 1; i++) { // 右上移动 height-1 步
                if (cy % 2 === 0) { // 偶数行：仅行减少
                    cy -= 1;
                } else { // 奇数行：行减少，列增加
                    cx += 1;
                    cy -= 1;
                }
                rightCells.push({ col: cx, row: cy });
            }
        }

        // 合并所有格子并去重
        const uniqueCells = new Map<string, Cell>(); // 使用 Map 去重
        for (const cell of [...cells, ...leftCells, ...rightCells]) {
            uniqueCells.set(`${cell.row},${cell.col}`, cell);
        }

        return Array.from(uniqueCells.values());
    }



}